package com.insight.modules.system.service.impl;

import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.insight.common.api.vo.Result;
import com.insight.common.constant.CommonConstant;
import com.insight.common.util.ImportExcelUtil;
import com.insight.modules.system.entity.SysRole;
import com.insight.modules.system.entity.SysThreePowerMenu;
import com.insight.modules.system.mapper.SysRoleMapper;
import com.insight.modules.system.mapper.SysUserMapper;
import com.insight.modules.system.service.ISysRoleService;
import org.jeecgframework.poi.excel.ExcelImportUtil;
import org.jeecgframework.poi.excel.entity.ImportParams;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.multipart.MultipartFile;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

/**
 * <p>
 * 角色表 服务实现类
 * </p>
 *
 * @Author scott
 * @since 2018-12-19
 */
/**
 * 角色管理服务实现类
 * 提供角色的增删查改、Excel导入校验、角色菜单权限等业务逻辑。
 */
@Service
public class SysRoleServiceImpl extends ServiceImpl<SysRoleMapper, SysRole> implements ISysRoleService {

    @Autowired
    SysRoleMapper sysRoleMapper; // 角色表操作 Mapper

    @Autowired
    SysUserMapper sysUserMapper; // 用户表操作 Mapper

    /**
     * 从 Excel 文件导入角色数据，同时校验 roleCode 的唯一性
     *
     * @param file   上传的 Excel 文件
     * @param params 导入参数（行数、标题等）
     * @return 返回导入结果，包括成功行数和错误行数
     * @throws Exception 文件解析或处理异常
     */
    @Override
    public Result importExcelCheckRoleCode(MultipartFile file, ImportParams params) throws IOException {
        // 解析 Excel 文件内容，转为 SysRole 实体列表
        List<Object> listSysRoles = null;
        try {
            listSysRoles = ExcelImportUtil.importExcel(file.getInputStream(), SysRole.class, params);
        } catch (Exception e) {
            throw new IllegalStateException("Excel 导入失败：系统内部错误", e);
        }
        int totalCount = listSysRoles.size();
        List<String> errorStrs = new ArrayList<>();

        // 检查导入数据中的重复 roleCode（同一个 Excel 文件内）
        for (int i = 0; i < listSysRoles.size(); i++) {
            String roleCodeI = ((SysRole) listSysRoles.get(i)).getRoleCode();
            for (int j = i + 1; j < listSysRoles.size(); j++) {
                String roleCodeJ = ((SysRole) listSysRoles.get(j)).getRoleCode();
                if (roleCodeI.equals(roleCodeJ)) {
                    errorStrs.add("第 " + (j + 1) + " 行的 roleCode 值：" + roleCodeI + " 已存在，忽略导入");
                    listSysRoles.remove(j);
                    break;
                }
            }
        }

        // 校验数据库中是否已存在重复 roleCode，避免违反唯一约束
        Integer errorLines = 0;
        Integer successLines = 0;
        List<String> list = ImportExcelUtil.importDateSave(listSysRoles, ISysRoleService.class, errorStrs, CommonConstant.SQL_INDEX_UNIQ_SYS_ROLE_CODE);
        errorLines += list.size();
        successLines += (listSysRoles.size() - errorLines);

        // 返回导入结果
        return ImportExcelUtil.imporReturnRes(errorLines, successLines, list);
    }

    /**
     * 根据角色 ID 删除角色及其关联关系
     *
     * @param roleid 要删除的角色 ID
     * @return true 删除成功
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean deleteRole(String roleid) {
        // 删除角色与用户关联关系
        sysRoleMapper.deleteRoleUserRelation(roleid);
        // 删除角色与权限关联关系
        sysRoleMapper.deleteRolePermissionRelation(roleid);
        // 删除角色本身
        this.removeById(roleid);
        return true;
    }

    /**
     * 批量删除多个角色及其关联关系
     *
     * @param roleIds 角色 ID 数组
     * @return true 删除成功
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean deleteBatchRole(String[] roleIds) {
        // 删除多个角色与用户之间的关联
        sysUserMapper.deleteBathRoleUserRelation(roleIds);
        // 删除多个角色与权限之间的关联
        sysUserMapper.deleteBathRolePermissionRelation(roleIds);
        // 删除角色记录
        this.removeByIds(Arrays.asList(roleIds));
        return true;
    }

    /**
     * 根据角色编码查询对应的三级菜单权限
     *
     * @param roleCode 角色编码
     * @return 菜单权限列表
     */
    @Override
    public List<SysThreePowerMenu> getSysThreepowerMenueByRoleCode(String roleCode) {
        return sysRoleMapper.getSysThreepowerMenueByRoleCode(roleCode);
    }

    /**
     * 根据菜单展示类型获取三级菜单权限
     *
     * @param showType 展示类型（如 PC、H5 等）
     * @return 权限菜单列表
     */
    @Override
    public List<SysThreePowerMenu> getSysThreepowerMenueByShowType(String showType) {
        return sysRoleMapper.getSysThreepowerMenueByShowType(showType);
    }

    /**
     * 根据角色编码查询角色信息
     *
     * @param relateId 角色编码
     * @return 角色信息
     */
    @Override
    public SysRole getInfoByRoleCode(String relateId) {
        return sysRoleMapper.getInfoByRoleCode(relateId);
    }

    /**
     * 根据用户 ID 查询其拥有的角色列表
     *
     * @param userId 用户 ID
     * @return 角色列表
     */
    @Override
    public List<SysRole> getInfoByUserId(String userId) {
        return sysRoleMapper.getInfoByUserId(userId);
    }

    /**
     * 判断当前用户是否拥有指定按钮权限角色
     *
     * @param role   按钮权限标识
     * @param userId 用户 ID
     * @return true 表示拥有按钮权限
     */
    @Override
    public Boolean hasButtonRole(String role, String userId) {
        return sysRoleMapper.hasButtonRole(role, userId) > 0;
    }
}

